﻿//
//  ZDT6.cs
//
//  Author:
//       Antonio J. Nebro <antonio@lcc.uma.es>
//
//  Copyright (c) 2011 Antonio J. Nebro
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
// 
//  You should have received a copy of the GNU Lesser General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using jmetal.core;
using jmetal.encodings.solutionType;

namespace jmetal.problems
{
  public class ZDT6 : Problem
  {

    public ZDT6 (String solutionType) : this(solutionType, 10)
    {
      // 30 variables by default
    }
    // ZDT1

    public ZDT6 (String solutionType, int numberOfVariables)
    {
      // <pex>
      if (numberOfVariables < 0)
        throw new ArgumentException("numberOfVariables < 0", "numberOfVariables");
      // </pex>
      numberOfVariables_ = numberOfVariables;
      numberOfObjectives_ = 2;
      numberOfConstraints_ = 0;
      problemName_ = "ZDT6";
      
      upperLimit_ = new double[numberOfVariables_];
      lowerLimit_ = new double[numberOfVariables_];
      
      // Establishes upper and lower limits for the variables
      for (int var = 0; var < numberOfVariables_; var++) {
        lowerLimit_[var] = 0.0;
        upperLimit_[var] = 1.0;
      }
      // for
      solutionType_ = new RealSolutionType (this);
    }
    // ZDT1
/** 
     * Evaluates a solution.
     * @param solution The solution to evaluate.
     * @throws JMException 
     */    
        public override void evaluate (Solution solution)
    {
      // <pex>
      if (solution == (Solution)null)
        throw new ArgumentNullException("solution");
      if (solution.variable_ == (Variable[])null)
        throw new ArgumentNullException("solution");
      // </pex>
      Variable[] x = solution.variable_;
      
      double x1 = x[0].value_;
      double[] f = new double[numberOfObjectives_];
      f[0] = 1.0 - Math.Exp ((-4.0) * x1) * Math.Pow (Math.Sin (6.0 * Math.PI * x1), 6.0);
      double g = this.evalG (x);
      double h = this.evalH (f[0], g);
      f[1] = h * g;
      
      solution.objective_[0] = f[0];
      solution.objective_[1] = f[1];
    }
    // evaluate
/**
     * Returns the value of the ZDT1 function G.
     * @param decisionVariables The decision variables of the solution to 
     * evaluate.
     * @throws JMException 
     */    
        private double evalG (Variable[] x)
    {
      double g = 0.0;
      for (int var = 1; var < this.numberOfVariables_; var++)
        g += x[var].value_;
      g = g / (numberOfVariables_ - 1);
      g = Math.Pow (g, 0.25);
      g = 9.0 * g;
      g = 1.0 + g;
      return g;
      
      
    }
    // evalG
/**
     * Returns the value of the ZDT1 function H.
     * @param f First argument of the function H.
     * @param g Second argument of the function H.
     */    
        public double evalH (double f, double g)
    {
      return 1.0 - Math.Pow ((f / g), 2.0);
      
    }
    // evalH
  }
}
